/************************************************************************/
/* particleVertex.cpp                                                   */
/* 2004/04/30                                                           */
/************************************************************************/

#include            <d3dx9.h>
#include            "dxutil.h"
#include            "recycleArray.h"
#include            "EventList.h"
#include            "Particle.h"
#include            "EffectDataStruct.h"
#include            "ParticleVertex.h"

/************************************************************************/
#include            "FXRenderState.h"

/************************************************************************/

//extern bool g_Effect;

/************************************************************************/
/*                                                                      */
/************************************************************************/
HRESULT CParticleVertexManager::RestoreDeviceObjects(
	LPDIRECT3DDEVICE9 pDevice, VertexBufferItem* pVB)
{
	m_pd3dDevice = pDevice;
	m_pVB = pVB;

	return S_OK;
}


/************************************************************************/
/*                                                                      */
/************************************************************************/
void CParticleVertexManager::RenewStrip(
										const float& fElapsedTime, EFFECT_DATA& fxdata)
{
	std::vector<SParticleVertex>::iterator partIter = 
		fxdata.pPartVertices->begin();

	while (partIter != fxdata.pPartVertices->end())
	{
		if (fxdata.bIsTrailOn == false) partIter->fAge += 200.0f;
		partIter->color = GetColor(partIter->fAge);

		if (!partIter->Update(fElapsedTime))
		{
			partIter = fxdata.pPartVertices->erase(partIter);
			continue;
		}
		++partIter;
	}
	return;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void CParticleVertexManager::Update(const float& fElapsedTime,
									EFFECT_DATA& fxdata, const D3DXVECTOR3& vMin, const D3DXVECTOR3& vMax)
{
	if (!fxdata.bIsTrailOn)
	{
		fxdata.bPartVertexFirstUpdate = true;
		return;
	}
	RenewStrip(fElapsedTime, fxdata);
	GenerateNewStrip(fxdata, vMin, vMax);
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void CParticleVertexManager::GenerateNewStrip(EFFECT_DATA& fxdata, 
											  const D3DXVECTOR3& vMin, const D3DXVECTOR3& vMax)
{
	SParticleVertex part;    
	part.fLifeTime = m_fLifeTime;
	part.vPosMin = vMin;
	part.vPosMax = vMax;
	part.fAge = 0.0f;
	part.color = GetColor(part.fAge);
	fxdata.vOldPartVertexPosMin = vMin;
	fxdata.vOldPartVertexPosMax = vMax;
	fxdata.pPartVertices->push_back(part);
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
HRESULT CParticleVertexManager::Render(EFFECT_DATA& fxdata)
{
	//	if(!g_Effect)	return S_OK;
	FX_COMMON_VERTEX* pVertices;
	int nNumParticlesToRender = 0;

	SetRenderState();

	m_pd3dDevice->SetTexture(0, 0);
	m_pd3dDevice->SetFVF(D3DFVF_FX_COMMON_VERTEX);
	m_pd3dDevice->SetVertexShader(NULL);
	//    m_pd3dDevice->SetStreamSource(0, m_pVB, 0, sizeof(FX_COMMON_VERTEX));
	m_pVB->activate(0,0,0);

	m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matIdentity);

	pVertices=(FX_COMMON_VERTEX* )m_pVB->lock(nWriteLock,0,0);

	PART_ITER partIter = fxdata.pPartVertices->begin();
	while (partIter != fxdata.pPartVertices->end())
	{
		pVertices->vPos.x = partIter->vPosMax.x;
		pVertices->vPos.y = partIter->vPosMax.y;
		pVertices->vPos.z = partIter->vPosMax.z;
		pVertices->u = 0.0f;
		pVertices->v = 0.0f;

		pVertices->dwColor = (DWORD)partIter->color;		
		pVertices++;
		++nNumParticlesToRender;

		pVertices->vPos.x = partIter->vPosMin.x;
		pVertices->vPos.y = partIter->vPosMin.y;
		pVertices->vPos.z = partIter->vPosMin.z;			
		pVertices->u = 0.0f;
		pVertices->v = 0.0f;
		D3DXCOLOR color = partIter->color - D3DXCOLOR(0.1F, 0.1F, 0.1F, 0.1F);
		pVertices->dwColor = (DWORD)color;
		pVertices++;
		++nNumParticlesToRender;

		if (nNumParticlesToRender == NUM_COMMON_VERTICES)
		{
			m_pVB->unlock();

			m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
				0, nNumParticlesToRender - 2);
			nNumParticlesToRender = 0;
			pVertices=(FX_COMMON_VERTEX* )m_pVB->lock(nWriteLock, 0,0);
			continue;
		}
		++partIter;
	}
	m_pVB->unlock();

	if (nNumParticlesToRender >= 2)
	{
		m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 
			nNumParticlesToRender - 2);
	}				
	return S_OK;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void
CParticleVertexManager::SetRenderState( void )
{
	m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	m_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
	m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
	m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
	m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
	m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
	m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
	m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
HRESULT CParticleVertexManager::DeleteObjectDevice()
{
	SAFE_RELEASE(m_pTexture);
	return S_OK;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void CParticleVertexManager::DecodeEventScript(const char* strEventScript)
{

	int nLineCount = 0;
	char strOutputString[256];
	char strRead[256];
	char strLine[256];
	char strGarbage[128];

	m_EventList.Clear();

	FILE* pStream = NULL;
	pStream = fopen(strEventScript, "rt");
	if(pStream == NULL)
	{
		sprintf(strOutputString, "Opend Failed: %s \n", strEventScript);
		OutputDebugString(strOutputString);
		return;
	}

	fgets(strLine, 256, pStream);
	sscanf(strLine, "%s", strRead);
	nLineCount++;

	if(_stricmp(strRead, "PARTICLE_VERTEX:") != 0)
	{
		sprintf(strOutputString, "Invalid data: %s:%d", strEventScript,
			nLineCount);
		return;
	}

	fgets(strLine, 256, pStream);
	sscanf(strLine, "%s", strRead);
	nLineCount++;
	if(_stricmp(strRead, "BEGIN") != 0)
	{
		sprintf(strOutputString, "Invalid data: %s", strEventScript, 
			nLineCount);
		return;
	}

	while (!feof(pStream))
	{
		++nLineCount;
		fgets(strLine, 256, pStream);
		if(_stricmp(strLine, "\n") == 0) continue;
		sscanf(strLine, "%s", strRead);

		if(_stricmp(strRead, "END") == 0)
		{
			fclose(pStream);
			return;
		}
		else if(_stricmp(strRead, "NAME") == 0)
		{
			continue;
		}

		else if(_stricmp(strRead, "ADDCOLOR") == 0)
		{
			float fTickNum, r, g, b, a;
			sscanf(strLine, "%s%f%f%f%f%f", strGarbage, &fTickNum, &r, &g,
				&b, &a);
			AddColor(fTickNum, D3DXCOLOR(r, g, b, a));
		}
		else if(_stricmp(strRead, "LIFE") == 0)
		{
			sscanf(strLine, "%s%f", strGarbage, &m_fLifeTime);
		}
		else if(_stricmp(strRead, "SRCBLEND") == 0)
		{

		}
		else if(_stricmp(strRead, "DESTBLEND") == 0)
		{

		}
		else if(_stricmp(strRead, "COLOROP") == 0)
		{

		}
		else if(_stricmp(strRead, "COLORARG1") == 0)
		{
		}
		else if(_stricmp(strRead, "COLORARG2") == 0)
		{
		}
		else if(_stricmp(strRead, "ALPHAARG1") == 0)
		{
		}
		else if(_stricmp(strRead, "ALPHAARG2") == 0)
		{
		}
		else if(_stricmp(strRead, "ALPHAOP") == 0)
		{
		}
		else
		{
			sprintf(strOutputString, "Invalid data: %s, %d, %s", strRead,
				nLineCount, strEventScript);
			OutputDebugString(strOutputString);
			fclose(pStream);
			return;
		}	
	}
	sprintf(strOutputString, "Unexpeted end of file: %d", nLineCount);
	OutputDebugString(strOutputString);
	fclose(pStream);
	return;
}



void CParticleVertexManager::SetColorEvent( int count, D3DXCOLOR particleColor, int time, int sizeR )
{
	m_EventList.Clear();
	if ( count > 6 )
		count = 6;

	float tickTime = 0.f;
	D3DXCOLOR newColor = particleColor;
	for ( int i = 0 ; i < count ;  )
	{		
		AddColor( tickTime, newColor );
		tickTime = ( count + ( time  * ++i ) ) * 2;
		newColor.a -= ( particleColor.g +count ) / ( sizeR );
		newColor.r -= ( particleColor.g +count ) / ( sizeR );
		newColor.g -= ( particleColor.g +count ) / ( sizeR );
		newColor.b -= ( particleColor.g +count ) / ( sizeR );
		if ( particleColor.a < 0 )
			particleColor.a = 0;
		if ( particleColor.r < 0 )
			particleColor.r = 0;
		if ( particleColor.g < 0 )
			particleColor.g = 0;
		if ( particleColor.b < 0 )
			particleColor.b = 0;
	}
	SetLifeTime( tickTime );
}